﻿from rrDefine import *
from rrFunc import *
from rrDice import *


#*******************************************************************************
#
#	OBJECT
#
#*******************************************************************************

class Object:
#generic objects, base class for player, NPC and all types of items
	def __init__(self):
		self.name=None
		self.x=None
		self.y=None
		self.sprite=None
		self.color=None
		self.bold=None
		self.blocked=None
		self.visible=None
	
	def move(self,dx,dy, map, objects):
		if not is_case_blocked(self.x+dx,self.y+dy, map, objects):
			self.x+=dx
			self.y+=dy
			return TURN_TAKEN
		return NONE
		
	def draw(self):
		if self.visible:
			init_pair(self.color,self.color,COLOR_BLACK);
			if self.bold:
				mvaddstr(self.y+1,self.x,str(self.sprite),COLOR_PAIR(self.color)|A_BOLD);
			else:
				mvaddstr(self.y+1,self.x,str(self.sprite),COLOR_PAIR(self.color));

#*******************************************************************************
#
#	FIGHTER
#
#*******************************************************************************

class Fighter(Object):
	def __init__(self):
		super(Figther, self).__init__()
		
		self.hit_dice=None
		self.armor_class=None
		self.attack=None
		self.aligment=None
		
#*******************************************************************************
#
#	Player
#
#*******************************************************************************

class Player(Fighter):
	def __init__(self,name):
		self.name=name
		self.sprite="@"
		self.color=COLOR_WHITE
		self.bold=True
		self.blocked=True
		self.visible=True
			
		self.size=MEDIUM #TODO
		self.align=NEUTRAL #TODO
		self.main_stat=0 #TODO
		
		#stats generation
		self.stats=[0,0,0,0,0,0]
		for i in range(6):
			self.stats[i]=roll_dice(3,6,0)
		self.stats[self.main_stat]+=2
		
		self.ac=7
		self.thac0=0 #TODO
		self.hd=Dice(1,6,self.stats[CON])
		self.lvl=1
		self.max_hp=self.hd.roll()
		self.cur_hp=self.max_hp
		self.max_mana=roll_dice(1, self.stats[WIS], self.stats[INT])
		self.cur_mana=self.max_mana
		self.power=0.1*self.lvl+0.05*self.stats[self.main_stat]
		self.gold=0
		self.exp=0
		self.nbkey=0 #number of key
		
		self.inventory=[]
		self.max_weight=self.stats[STR]*10.0
		self.cur_weight=0.0
		
		#player specifics
		self.hunger=1000
		self.starvation_threshold=-200-self.stats[CON]*20
		
		self.class_type=ASSASSIN #TODO
		self.race_type=CATFOLK #TODO
	
	
	def draw_inventory(self,objects, map):
		blit_screen(self, objects, map)
		mvaddstr(0,0,"INVENTORY ("+str(self.cur_weight)+"/"+str(self.max_weight)+"lbs), "+str(self.nbkey)+" keys")
		
		i=1
		k=1
		for obj in self.inventory:
			mvaddstr(i,0,"("+str(k)+") "+obj.name)
			k+=1
			i+=1
		return handle_key(self, objects, map)
	
	def get_hunger(self):
		if self.hunger>=2000:
			return FULL
		elif self.hunger >=1000 and self.hunger <2000:
			return SATIATED
		elif self.hunger >=150 and self.hunger <1000:
			return NOT_HUNGRY
		elif self.hunger >=50 and self.hunger <150:
			return HUNGRY
		elif self.hunger >=self.starvation_threshold and self.hunger <50:
			return STARVING
		else:
			return STARVED_TO_DEATH
	
	def level_up(self):
		if self.lvl<MAX_CH_LVL:
			self.lvl+=1
			self.power+=0.1*self.lvl+0.05*self.stats[self.main_stat]
			self.max_hp+=self.hd.roll()
			self.cur_hp=self.max_hp
			self.max_mana+=roll_dice(1, self.stats[WIS], self.stats[INT])
			self.cur_mana=self.max_mana
			
	def pick_up(self, objects, map):
		
		blit_screen(self, objects, map)
		rec_pu=[] #recently picked up objects
		pu=False #wether something has been picked up or not

		for obj in objects:
			if obj.x==self.x and obj.y==self.y and obj!=self:
				if(self.cur_weight+obj.weight<=self.max_weight):
					self.inventory.append(obj)
					rec_pu.append(obj)
					objects.remove(obj)
					self.cur_weight+=obj.weight
					pu=True
				else:
					mvaddstr(0,0,'you are overloaded. drop something first')
				
		if pu==False:
			mvaddstr(0,0,'nothing to pick up')
			
		else:
			for obj in rec_pu:
				mvaddstr(0,0,'picked up '+obj.name)
				
		clrtoeol()
		refresh()
		return handle_key(self, objects, map)
	
	def open_door(self, objects, map):
		blit_screen(self, objects, map)
		c=wait_direction()
		dx=0
		dy=0
		direction=""
		
		if c==258:
			dx=0
			dy=1
			direction="south"
		elif c==259:
			dx=0
			dy=-1
			direction="north"
		elif c==260:
			dx=-1
			dy=0
			direction="west"
		elif c==261:
			dx=+1
			dy=0
			direction="east"
			
		if map[self.x+dx][self.y+dy].type==U_DOOR:
			map[self.x+dx][self.y+dy].set_type(O_DOOR)
			mvaddstr(0,0,"door opened")
			
		elif map[self.x+dx][self.y+dy].type==L_DOOR:
			if self.nbkey==0:
				mvaddstr(0,0,"door locked, must find a key...")
			else:
				map[self.x+dx][self.y+dy].set_type(O_DOOR)
				mvaddstr(0,0,"door unlocked!")
				self.nbkey-=1
				if self.nbkey<0:
					self.nbkey=0
		else:
			mvaddstr(0,0,"no door to the "+direction)
			
		clrtoeol()
		refresh()
		return handle_key(self, objects, map)
	
#*******************************************************************************
#
#	NPC
#
#*******************************************************************************

class NPC(Fighter):
	def __init__(self,line):
		self.name=""
		self.sprite=""
		self.color=None
		self.bold=None
		self.blocked=True
		self.visible=False
		
		self.size=MEDIUM #TODO
		self.align=NEUTRAL #TODO
		self.main_stat=0 #TODO
		#stats generation
		self.stats=[0,0,0,0,0,0]
		for i in range(6):
			self.stats[i]=roll_dice(3,6,0)
		self.stats[self.main_stat]+=2
		
		self.ac=7
		self.thac0=0 #TODO
		self.hd=Dice(1,6,self.stats[CON])
		self.lvl=1
		self.max_hp=self.hd.roll()
		self.cur_hp=self.max_hp
		self.max_mana=roll_dice(1, self.stats[WIS], self.stats[INT])
		self.cur_mana=self.max_mana
		self.power=0.1*self.lvl+0.05*self.stats[self.main_stat]
		self.gold=0
		self.exp=0
				
#*******************************************************************************
#
#	ITEMS
#
#*******************************************************************************

class Food(Object):
	def __init__(self):
		self.weight=0
		self.price=0
		self.effect=None #function of what it does

class Drink(Object):
	def __init__(self):
		self.weight=0
		self.price=0
		self.effect=None #function of what it does
		
class Armor(Object):
	def __init__(self,dlvl):
		self.name='Armor'
		self.x=None
		self.y=None
		self.sprite='['
		self.color=COLOR_RED
		self.bold=False
		self.blocked=False
		self.visible=False
		self.weight=0
		self.price=0

class MeleeWeapon(Object):
	def __init__(self,dlvl):
		#generate random weapon given dungeon level
		#m_weapon = type slot price weight hit damage
		#slot = 1 hand or 2 handed
			
		#determine weapon quality
		q=get_quality(dlvl)
			
		quality=WA_QUALITY[q]
		#determine weapon type
		t_chance=get_m_type()
		type=M_WEAPON_TYPE[t_chance]
			
		#determine number of slot
		if t_chance==DAGGER:
		#dagger is always 1 handed
			slot=1
			slot_bonus=0
		elif t_chance==STAFF or t_chance==POLEARM:
		#staff and polearm are always 2 handed
			slot=2
			slot_bonus=2
		else:
		#every other weapon can either be 1 or 2 handed
			slot=random.randint(1,100)
		
		if(slot>60):
			slot=2
			slot_bonus=2
		else:
			slot=1 #1 handed weapons are more common
			slot_bonus=0
			
		#determine damage
		damage=Dice(MW_QUALITY_ROLL[q],MW_TYPE_DMG[t_chance]+slot_bonus,MW_QUALITY_DMG[q])
		
		
		#determine hit
		hit=MW_TYPE_HIT[t_chance]+MW_QUALITY_HIT[q]
			
		if slot==2:
			wp_ratio=2
		else:
			wp_ratio=1
			
		#determine weight
		weight=MW_TYPE_WEIGHT[t_chance]*MW_QUALITY_WEIGHT[q]*wp_ratio
		#determine price
		price=int(MW_TYPE_PRICE[t_chance]*MW_QUALITY_PRICE[q]*wp_ratio)
			
		#final weapon
		self.name=str(slot)+"h "+quality+" "+type+"(+"+str(hit)+", "+damage.toString()+")"
		self.x=0
		self.y=0
		self.sprite="("
		self.color=COLOR_BLUE
		self.bold=False
		self.blocked=False
		self.visible=False
		self.slot=slot
		self.quality=quality
		self.type=type
		self.damage=damage
		self.hit=hit
		self.weight=weight
		self.price=price

class RangedWeapon(Object):
	def __init__(self,dlvl):
		self.weight=0
		self.price=0
		
class Ammunition(Object):
	def __init__(self,dlvl):
		self.weight=0
		self.price=0